package com.adcc.loadSheetForwarder.service;

import com.adcc.loadSheetForwarder.configuration.UmeTripProperties;
import com.adcc.loadSheetForwarder.entity.Flight;
import com.adcc.loadSheetForwarder.entity.LoadSheet;
import com.adcc.loadSheetForwarder.utils.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.security.MessageDigest;
import java.util.*;

@Service
@Slf4j
public class UmeServiceImpl implements UmeService {
    private static final String hexDigits[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};

    @Autowired
    UmeTripProperties properties;
    @Autowired
    RestClient restClient;

    @Override
    public List<Flight> getFlights(Map<String, Object> paramMap) throws LoadSheetException {
        List<Flight> flights = Lists.newArrayList();
        // 设置通用参数
        setCommonParam(paramMap);
        Map<String, Object> resultMap = restClient.umeJsonStringPost(properties.getFlightsUrl(), paramMap);
        if (resultMap.containsKey(SystemConst.REST_CLIENT_ERROR_KEY)) {
            this.failCount.incrementAndGet();
            ResultCode errorResult = (ResultCode) resultMap.get(SystemConst.REST_CLIENT_ERROR_KEY);
            throw new LoadSheetException(errorResult.getMsg(), errorResult.getCode());
        }
        int resultCode = (int) resultMap.get("errCode");
        if (resultCode != 0) {
            this.failCount.incrementAndGet();
            throw new LoadSheetException(ResultCode.UME_RETURN_DATA_ERROR.getMsg(), ResultCode.UME_RETURN_DATA_ERROR.getCode());
        }
        if (!resultMap.containsKey("umetripLdpMsgListDto")) {
            this.failCount.incrementAndGet();
            return Lists.newArrayList();
        }
        // 调用成功一次就将调用失败次数归零
        this.failCount.getAndSet(0);
        JSONArray flightArray = (JSONArray) resultMap.get("umetripLdpMsgListDto");
        flightArray.forEach(flight -> {
            flights.add(JSON.parseObject(flight.toString(), Flight.class));
        });
        return flights;
    }

    @Override
    public LoadSheet getOriginalLoadSheet(Map<String, Object> paramMap) throws LoadSheetException {
        // 设置通用参数
        setCommonParam(paramMap);
        Map<String, Object> resultMap = restClient.umeJsonStringPost(properties.getOriginalLoadSheetUrl(), paramMap);
        if (resultMap.containsKey(SystemConst.REST_CLIENT_ERROR_KEY)) {
            this.failCount.incrementAndGet();
            ResultCode errorResult = (ResultCode) resultMap.get(SystemConst.REST_CLIENT_ERROR_KEY);
            throw new LoadSheetException(errorResult.getMsg(), errorResult.getCode());
        }
        int resultCode = (int) resultMap.get("errCode");
        if (resultCode != 0) {
            this.failCount.incrementAndGet();
            throw new LoadSheetException(ResultCode.UME_RETURN_DATA_ERROR.getMsg(), ResultCode.UME_RETURN_DATA_ERROR.getCode());
        }

        if (!resultMap.containsKey("umetripLdpMsgListDto")) {
            this.failCount.incrementAndGet();
            throw new LoadSheetException(ResultCode.UME_RETURN_DATA_ERROR.getMsg(), ResultCode.UME_RETURN_DATA_ERROR.getCode());
        }
        // 调用成功一次就将调用失败次数归零
        this.failCount.getAndSet(0);
        JSONArray loadSheetArray = (JSONArray) resultMap.get("umetripLdpMsgListDto");
        if (loadSheetArray.isEmpty()) {
            throw new LoadSheetException(ResultCode.UME_RETURN_DATA_EMPTY.getMsg(), ResultCode.UME_RETURN_DATA_EMPTY.getCode());
        }
        return JSON.parseObject(loadSheetArray.get(0).toString(), LoadSheet.class);
    }

    @Override
    public void checkUmeStatus() {
        try {
            String traceid = UUID.randomUUID().toString();
            Map<String, Object> paramMap = Maps.newHashMap();
            paramMap.put("flightNo", properties.getTestFlightNumber());
            paramMap.put("flightDate", new LocalDate().toString());
            paramMap.put("deptAirport", "PEK");
            paramMap.put("arrAirport", "");
            paramMap.put("aircraftNo", "");
            paramMap.put("traceid", traceid);
            setCommonParam(paramMap);
            Map<String, Object> resultMap = restClient.umeJsonStringPost(properties.getFlightsUrl(), paramMap);
            if (resultMap.containsKey(SystemConst.REST_CLIENT_ERROR_KEY)) {
                this.failCount.incrementAndGet();
                return;
            }
            // 调用成功一次就将调用失败次数归零
            this.failCount.getAndSet(0);
        } catch (Exception e) {
            log.info("checkUmeStatus error()", e);
        }
    }

    /**
     * 设置通用参数
     *
     * @param paramMap
     */
    private void setCommonParam(Map<String, Object> paramMap) {
        paramMap.put("appid", properties.getAppId());
        paramMap.put("timestamp", DateTimeUtil.getNowTimeStamp());
        if (!paramMap.containsKey("version")) {
            paramMap.put("version", "1.0");
        }
        paramMap.put("type", "SIGN_MD5");
        SortedMap<Object, Object> sortedMap = new TreeMap<>(paramMap);
        paramMap.put("sign", createSign("UTF-8", sortedMap, properties.getAppSecret()));
    }

    /**
     * 生成校验码
     *
     * @param characterEncoding
     * @param parameters
     * @param appsecret
     * @return
     */
    public String createSign(String characterEncoding, SortedMap<Object, Object> parameters, String appsecret) {
        StringBuffer sb = new StringBuffer();
        Set es = parameters.entrySet();
        Iterator it = es.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String k = (String) entry.getKey();
            Object v = entry.getValue();
            if (null != v && !"".equals(v)
                    && !"sign".equals(k) && !"key".equals(k)) {
                sb.append(k + "=" + v);
            }
        }
        sb.append("appsecret=" + appsecret);
        String sign = MD5Encode(sb.toString(), characterEncoding).toUpperCase();
        return sign;
    }


    /**
     * MD5加密
     *
     * @param origin
     * @param charsetname
     * @return
     */
    public String MD5Encode(String origin, String charsetname) {
        String resultString = null;
        try {
            resultString = new String(origin);
            MessageDigest md = MessageDigest.getInstance("MD5");
            if (charsetname == null || "".equals(charsetname)) {
                resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
            } else {
                resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));
            }
        } catch (Exception exception) {
        }
        return resultString;
    }

    private String byteArrayToHexString(byte b[]) {
        StringBuffer resultSb = new StringBuffer();
        for (int i = 0; i < b.length; i++) {
            resultSb.append(byteToHexString(b[i]));
        }
        return resultSb.toString();
    }

    private String byteToHexString(byte b) {
        int n = b;
        if (n < 0)
            n += 256;
        int d1 = n / 16;
        int d2 = n % 16;
        return hexDigits[d1] + hexDigits[d2];
    }
}
